/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
//package loganalysis;

/**
 *
 * @author prateek
 */

import java.io.*;
import java.io.*;
//import java.text.DateFormat;
import java.util.*;
import java.util.Date.*;
import java.text.SimpleDateFormat;
import java.math.*;

public class bgpLogsIntermediateData {
     private ArrayList<ArrayList<String>> logData ;
    private BufferedReader loadLogFile;
    private int numOfTasks;
    private int numOfWorkers;
    private Set workersInJob;
   // private int [] totalTime;
    private static BufferedReader loadInputFile;
    private long timeMS;
    private String timeStampOfData;
    private long minExecutionTimeStamp;
    private long maxExecutionTimeStamp;
    private long avgWaitQueueTime;
    private long averageExecTime;
    private long avgResultQueueTime;
    private long avgTotalTime;
    private double waitQueueTime [];
    private double execTime[];
    private double resultQueueTime[];
    private double  totalTimeCon[];
    private long devWaitQueueTime;
    private long devExecTime;
    private long devResultQueueTime;
    private long  devTotalTimeCon;
    private long failedTask;
    private double efficiency;
    
    //Main Function
     public static void main(String[] args)  {
         
         
         bgpLogsIntermediateData obj = new bgpLogsIntermediateData();
         //Take input as txt file which contains path of input file and genrate the intermidate data 
         try{
         loadInputFile  = new BufferedReader(new FileReader ("/home/prateek/CS595/gto_linux_640GB/falkon_logs_history/logs_history/bgp/intrepid/List.txt"));
        
         }catch(FileNotFoundException e )
         {
         System.err.println("Error in List.txt : "+e);
         }
         String filePath = "";
        
         //ArrayList <String> arrayOfFilePath = new ArrayList<String>();
         //Loop for filePath
         try{
            //Initiaitng intermidiateData object 
            FileWriter intermidiateData = new FileWriter ("/home/prateek/CS595/gto_linux_640GB/falkon_logs_history/logs_history/bgp/intrepid/graph.txt" ,false);
            BufferedWriter fileForGraph = new BufferedWriter(intermidiateData); 
//                fileForGraph.write("timeStampOfData TimeinMS averageExecTime NumOfWorkers MaxExecTimeStamp MinExecTimeStamp NumofTasks");
//                fileForGraph.newLine();
            int i =1;
                while ((filePath=loadInputFile.readLine())!=null)
                    {
                        
                            System.out.println("--------------------------");
                            System.out.println("File location is  "+filePath);
                            obj.ScanData(filePath);
                            try{
                                  if(obj.CheckEmptyFile())
                                  {
                                    obj.CalculateTime();
                                    obj.setNumOfTasks();
                                    System.out.println("Rows Cured "+obj.Curration());
                                    System.out.println(obj.getNumOfTasks());
                                  // fileForGraph.write(obj.getTimeStampOfData()+" ");
                                   fileForGraph.write(i+" "); 
                                   fileForGraph.write(obj.getTimeMS()+" ");
                                   obj.NumberOfWorkers();
                                   fileForGraph.write(obj.numOfWorkers+" "); 
                                    obj.MaxExecution();
                                   fileForGraph.write(obj.getMaxExecutionTimeStamp()+" "); 
                                    obj.MinExecution();
                                   fileForGraph.write(obj.getMinExecutionTimeStamp()+" ");
                                   fileForGraph.write(Integer.toString(obj.numOfTasks)+" "); 
                                   //Average timing
                                   obj.AverageTime();
                                   fileForGraph.write(obj.getAvgWaitQueueTime()+" ");
                                   fileForGraph.write(obj.getAverageExecTime()+" ");
                                   fileForGraph.write(obj.getAvgResultQueueTime()+" ");
                                   fileForGraph.write(obj.getAvgTotalTime()+" ");
                                   
                                   //Deviation
                                   obj.CalculateDeviation();
                                   fileForGraph.write(obj.devWaitQueueTime+" ");
                                   fileForGraph.write(obj.devExecTime+" ");
                                   fileForGraph.write(obj.devResultQueueTime+" ");
                                   fileForGraph.write(obj.devTotalTimeCon+" ");
                                  
                                   //failedTask
                                   obj.FailedTask();
                                   fileForGraph.write(obj.failedTask+" ");
                                   
                                   //Efficiency
                                   obj.CalEfficiency();
                                   fileForGraph.write(obj.efficiency+"");
                                   //Next New Line
                                   i++;
                                   fileForGraph.newLine();
                                  } 
                            }catch(IndexOutOfBoundsException e){System.err.println("I hate this error"+e);}

                            System.out.println("--------------------------");

                          
                    }
                fileForGraph.close();
         }
         catch(IOException e)
         {
             System.err.println("Error in generating parameters : "+e);
         }
        
        // Tesing region 
//        Iterator list = obj.logData.iterator();
//        while(list.hasNext())
//        {
//            System.out.println(list.next());
//        }                   
       
    }
    public void ScanData(String filePath)
       {
            String fullFilePath = "/home/prateek/CS595/gto_linux_640GB/falkon_logs_history/logs_history/bgp/intrepid/"+filePath;
            String line ="";
            //2D Array
         logData = new ArrayList<ArrayList<String>>();
             //Create file object and read it 
            try {
            loadLogFile= new BufferedReader(new FileReader (""+fullFilePath));
                }
            catch(FileNotFoundException e)
                {
                    System.err.println("Error in finding log file: "+e);
                }
        //Initialize Row and column counter
         int row = 0;
         int col = 0;
         //Nested Loops to read file 
         try{
         while( (line = loadLogFile.readLine())!=null)
         {
             Scanner scanLine = new Scanner(line);
             logData.add(new ArrayList<String>());
             while(scanLine.hasNext())
             {
                 logData.get(row).add(scanLine.next());
                 col++;
             }
             row++;
         }
         //this.numOfTasks = row-1;
        //System.out.println("Value of number of Rows "+this.numOfTasks);
         }
         catch(IOException e)
         {
             System.err.println("Error in reading logs: "+e);
         }
     
      
         //ArrayList<String> ar = logData.get(numOfTasks);
         
       } 
    public boolean CheckEmptyFile ()
    {
    
        if(logData.get(0).get(0).isEmpty())
        {
        return false;
        }
        else
        {
        return true;
        }
    }
    
    public void CalculateTime()
    {
        //Function to calculate the current time from epoch time on the log.
        
        timeMS = Long.parseLong((logData.get(1).get(2)).replace("ms", ""));
        timeStampOfData =  this.EpochTimeCalculator(timeMS);
        System.out.println("Time Stamp Of Data "+timeStampOfData);
         
        //Removing the Top two rows 
         logData.remove(0);
         logData.remove(0);
        
         
         
     }

    public int Curration()
    {
       int cured =0;
       int k = logData.size();
       ArrayList<String> remove;
       for (int i =0;i<k;i++)
       {    
        //   System.out.println("Row is "+ i);
         //  System.out.println(logData.get(i));
             try{
               for(int j =0;j<12;j++){
               if(logData.get(i).get(j).toString()==null)
                        {
                        //call code to curate the tmp file
                        }
                   }
                   }catch(IndexOutOfBoundsException e)
                   {
                   System.out.println("Error in line " + e);
                   System.out.println("Index of Row "+i);
                   logData.remove(i);
                   cured++;
                   }
       
           
       }
       return cured;
    }
    
    public void NumberOfWorkers()
    {
         //Function to find the number of workers (CPUs used)..inserted into the set
         workersInJob = new HashSet();
         
         for (int i =0;i<logData.size();i++)
         {
         String workers=logData.get(i).get(2);
         String [] token = workers.split(":");
         workersInJob.add(token[0]);
         }
         //Number of Workers
         numOfWorkers = workersInJob.size();
         System.out.println(numOfWorkers);
    }
    
    //Average of all timings
    public void AverageTime()
    {
         //Calculate average complition 
         //Total time 
         int myNumofTask = logData.size();
         long totalWaitQueueTime=0;
         long totalExecTime=0;
         long totalResultQueueTime=0;
         long totalTime=0;
         
         waitQueueTime  = new double [myNumofTask] ;
         execTime= new double [myNumofTask] ;
         resultQueueTime= new double [myNumofTask] ;
         totalTimeCon= new double [myNumofTask] ;
         System.out.println("Num of Task in Average "+myNumofTask);
        // int [] totalTime = new int [myNumofTask];
         for (int i =0 ; i<myNumofTask; i++)
         {
             waitQueueTime[i]= Long.parseLong(logData.get(i).get(7));
             totalWaitQueueTime+=waitQueueTime[i];
             
             execTime[i]= Long.parseLong(logData.get(i).get(8));
             totalExecTime+= execTime[i];
             
             resultQueueTime[i]=Long.parseLong(logData.get(i).get(9));
             totalResultQueueTime+=resultQueueTime[i];
             
             totalTimeCon[i]=Long.parseLong(logData.get(i).get(10));
             totalTime+=totalTimeCon[i];
         }
        
            avgWaitQueueTime=totalWaitQueueTime/myNumofTask;
            averageExecTime=totalExecTime/myNumofTask;
            avgResultQueueTime=totalResultQueueTime/myNumofTask;
            avgTotalTime=totalTime/myNumofTask;
          System.out.println("Average W8Q time  "+avgWaitQueueTime);   
          System.out.println("Average complition time  "+averageExecTime);
          System.out.println("Average ResultQTime "+avgResultQueueTime);
          System.out.println("Average Total Time "+avgTotalTime);
    }

    public void CalculateDeviation()
    {
         devWaitQueueTime=(long)this.Deviation(waitQueueTime,avgWaitQueueTime);
         devExecTime=(long)this.Deviation(execTime,averageExecTime);
         devResultQueueTime=(long)this.Deviation(resultQueueTime,avgResultQueueTime);
         devTotalTimeCon=(long)this.Deviation(totalTimeCon,avgTotalTime);
        
    
    }
    
    public double Deviation(double []value,long avg)
    {
     
        
        double sum = 0.0;
        double dev = 0.0;
        int totalTask = logData.size();
        for(int i =0;i< totalTask;i++)
                {
                    sum+=Math.pow((value[i]-avg),2 );
                }
        dev =  Math.sqrt(sum/totalTask);
        System.out.println("Standard Deviation "+dev);
        return dev;
    
    }
    public void MinExecution()
    {
             Long exectime[] = new Long [logData.size()];
             for (int i =0 ; i<logData.size(); i++)
                {
                    exectime[i]= Long.valueOf(logData.get(i).get(4));
                    
                }
            Arrays.sort(exectime);
            //Min Execution time
            minExecutionTimeStamp = timeMS+exectime[0];
            System.out.println("Min Exec Time Stamp "+minExecutionTimeStamp);
            
    }
    public void MaxExecution()
    {
             Long exectime[] = new Long [logData.size()];
             for (int i =0 ; i<logData.size(); i++)
                {
                    exectime[i]= Long.valueOf(logData.get(i).get(4));
                    
                }
            Arrays.sort(exectime);
            //Max execution time
            maxExecutionTimeStamp = timeMS+exectime[(logData.size())-1];
            System.out.println("Max Exec Time Stamp"+maxExecutionTimeStamp);
    }
    
    public String EpochTimeCalculator(Long time)
    {
         Date epoch = new Date(time);
         SimpleDateFormat fDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
         String actualDate = fDate.format(epoch);
         return actualDate;
    }
    
    
    public void FailedTask()
    {
        failedTask=0;
        for(int i=0;i<logData.size();i++)
        {
            if(Long.parseLong(logData.get(i).get(11))!=0)
            {
                failedTask++;
            }
        
        }
    }
    
    public void CalEfficiency()
    {
        int totalTask = logData.size();
        long minTime=this.MinStartTime();
        System.out.println("Min Time "+minTime);
        long maxTime=this.MaxEndTime();
        System.out.println("Max Time "+maxTime);
        long avgtime = this.getAverageExecTime();
        System.out.println("Average Exec Time "+avgtime);
        int workers = this.getNumOfWorkers();
        System.out.println("Total Workers "+workers);
        long timeDif = maxTime-minTime;
        System.out.println("Time Difference "+timeDif);
        //Formula by Prof Ioan .
        efficiency=(totalTask*avgtime)/(workers*timeDif);
        System.out.println("Efficiency is "+efficiency);
    
    }
     public long MinStartTime()
    {
             Long exectime[] = new Long [logData.size()];
             for (int i =0 ; i<logData.size(); i++)
                {
                    exectime[i]= Long.valueOf(logData.get(i).get(3));
                    
                }
            Arrays.sort(exectime);
            //Min Execution time
            return exectime[0];
            
            
    }
    public long MaxEndTime()
    {
             Long exectime[] = new Long [logData.size()];
             for (int i =0 ; i<logData.size(); i++)
                {
                    exectime[i]= Long.valueOf(logData.get(i).get(6));
                    
                }
            Arrays.sort(exectime);
            //Max execution time
            return exectime[(logData.size())-1];
            
    }
    
      
    
    //Getter and Setter
    public BufferedReader getLoadLogFile() {
        return loadLogFile;
    }

    public void setLoadLogFile(BufferedReader loadLogFile) {
        this.loadLogFile = loadLogFile;
    }

    public ArrayList<ArrayList<String>> getLogData() {
        return logData;
    }

    public void setLogData(ArrayList<ArrayList<String>> logData) {
        this.logData = logData;
    }

    public int getNumOfTasks() {
        return numOfTasks;
    }

    public void setNumOfTasks() {
       
         this.numOfTasks = logData.size();
    }

    public int getNumOfWorkers() {
        return numOfWorkers;
    }

    public void setNumOfWorkers(int numOfWorkers) {
        this.numOfWorkers = numOfWorkers;
    }

    public Long getTimeMS() {
        return timeMS;
    }

    public void setTimeMS(Long timeMS) {
        this.timeMS = timeMS;
    }

    public Set getWorkersInJob() {
        return workersInJob;
    }

    public void setWorkersInJob(Set workersInJob) {
        this.workersInJob = workersInJob;
    }

      public void setTimeMS(long timeMS) {
        this.timeMS = timeMS;
    }

    public String getTimeStampOfData() {
        return timeStampOfData;
    }
        
    public long getMaxExecutionTimeStamp() {
        return maxExecutionTimeStamp;
    }

    public long getMinExecutionTimeStamp() {
        return minExecutionTimeStamp;
    }

    public long getAvgWaitQueueTime() {
        return avgWaitQueueTime;
    }

    public long getAvgResultQueueTime() {
        return avgResultQueueTime;
    }

    public long getAverageExecTime() {
        return averageExecTime;
    }

    public long getAvgTotalTime() {
        return avgTotalTime;
    }

    public long getDevExecTime() {
        return devExecTime;
    }

    public long getDevResultQueueTime() {
        return devResultQueueTime;
    }

    public long getDevTotalTimeCon() {
        return devTotalTimeCon;
    }

    public long getDevWaitQueueTime() {
        return devWaitQueueTime;
    }

    public long getFailedTask() {
        return failedTask;
    }

    public double getEfficiency() {
        return efficiency;
    }

     
    
   
}
